package tpalgo3.modelo.enemigos;

import java.awt.Point;
import java.util.Observable;

import org.apache.log4j.Logger;

import tpalgo3.entidades.Jugador;
import tpalgo3.modelo.tablero.Camino;
import tpalgo3.modelo.tablero.Casillero;

public abstract class Enemigo extends Observable {
	private static final Logger logger = Logger.getLogger(Enemigo.class);
	
	protected static final int DIVISOR_TURNOS = 20;
	
	private double velocidadActual;
	private int resistenciaActual;
	private Point posicion;
	private Integer numeroCasillero;
	private boolean fueraDelTablero = false;
	protected boolean afectadoPorArena;
	protected boolean afectadoPorPegote;
	private long turnoProximoMovimiento = 0;
		
	public double getVelocidadActual() {
		return velocidadActual;
	}
	public void setVelocidadActual(double velocidadActual) {
		this.velocidadActual = velocidadActual;
	}
	public int getResistenciaActual() {
		return resistenciaActual;
	}
	public void setResistenciaActual(int resistenciaActual) {
		this.resistenciaActual = resistenciaActual;
	}
	public Point getPosicion() {
		return posicion;
	}
	public void setPosicion(Point posicion) {
		this.posicion = posicion;
		setChanged();
		notifyObservers();
	}	
	public Integer getNumeroCasillero() {
		return numeroCasillero;
	}
	public void setNumeroCasillero(Integer numeroCasillero) {
		this.numeroCasillero = numeroCasillero;
	}
	public boolean isFueraDelTablero() {
		return fueraDelTablero;
	}
	public void setFueraDelTablero(boolean fueraDelTablero) {
		this.fueraDelTablero = fueraDelTablero;
		setChanged();
		notifyObservers();
	}
	public long getTurnoProximoMovimiento() {
		return turnoProximoMovimiento;
	}
	public void setTurnoProximoMovimiento(long turnoProximoMovimiento) {
		this.turnoProximoMovimiento = turnoProximoMovimiento;
	}
	public abstract boolean isAfectadoPorArena();
	public abstract void setAfectadoPorArena(boolean afectadoPorArena);
	public abstract boolean isAfectadoPorPegote();
	public abstract void setAfectadoPorPegote(boolean afectadoPorPegote);
	
	public void daniar(int danio) {
		resistenciaActual = resistenciaActual - danio;
		setChanged();
		notifyObservers();
	}
	
	public void reducirVelocidad(int porcentaje) {
		velocidadActual = velocidadActual - (velocidadActual * ((double)porcentaje / 100));
	}
	
	public void detener() {
		velocidadActual = 0;
	}
	
	public abstract void restituirVelocidad();
	
	public void obtenerEstado() {
		logger.info("CLASE: " + this.getClass().getName() + " - Posicion = " + posicion.toString() + " - Esta vivo? " + (tieneResistencia() ? "Si" : "No"));
	}
	
	public boolean tieneResistencia() {
		if (resistenciaActual > 0)
			return true;
		else return false;
	}
	
	public void mover(long turno, Camino camino, Jugador jugador) {
		if (puedoMover(turno, camino)) {
			logger.info("Velocidad actual: " + getVelocidadActual());
			if (getNumeroCasillero() < camino.puertaSalida()){
				Casillero destino = camino.siguiente(getNumeroCasillero());
				setPosicion(destino.getPosicion());
				setNumeroCasillero(destino.getOrdenCasillero());
				logger.info("Soy " + this.getClass().getName() + ". Me movi a: " + getPosicion().toString() + " - Numero de casilla: " + getNumeroCasillero());
				if (Terrestre.class.isInstance(this)) {
					((Terrestre)this).setAfectadoPorArena(false);
					((Terrestre)this).setAfectadoPorPegote(false);
					restituirVelocidad();
				}
			}
			else {
				setNumeroCasillero(getNumeroCasillero() + 1);
				camino.decrementarEnemigos();
				jugador.decrementarVida();
				setFueraDelTablero(true);
				logger.info("Soy " + this.getClass().getName() + ". Acabo de salir del tablero.");
			}
		}
	}
	
	private boolean puedoMover(long turno, Camino camino) {
		boolean resultado;
		if (getNumeroCasillero() > camino.puertaSalida()) {
			resultado = false;
		} 
		else {
			if (getVelocidadActual() == 0) {
				((Terrestre)this).incrementarTimerEsperaPorPegote();
				if (((Terrestre)this).getTimerEsperaPorPegote() < ((Terrestre)this).getTiempoEsperaPorPegote())
					resultado = false;
				else {
					logger.info("Soy " + this.getClass().getName() + ". Me puedo mover - TURNO: " + turno + " - VELOCIDAD: " + getVelocidadActual());
					resultado = true;
				}
			}
			else {
				if (turno != getTurnoProximoMovimiento())
					resultado = false;
				else
					resultado = true;
			}
		}
		if (resultado) {
			logger.info("Soy " + this.getClass().getName() + ". Me puedo mover - TURNO: " + turno + " - VELOCIDAD: " + getVelocidadActual());
			setTurnoProximoMovimiento(getTurnoProximoMovimiento() + ((long)(DIVISOR_TURNOS / getVelocidadActual())));
		}
		return resultado;
	}	
}